





<!DOCTYPE html>
<html class="writer-html5" lang="zh-CN" >
<head>
  <meta charset="utf-8">
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <title>Bring Your Own Datatypes to TVM &mdash; tvm 0.8.dev1982 文档</title>
  

  
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
  <link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/gallery.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/css/tlcpack_theme.css" type="text/css" />

  
  
    <link rel="shortcut icon" href="../../_static/tvm-logo-square.png"/>
  

  
  
  
  
    
      <script type="text/javascript" id="documentation_options" data-url_root="../../" src="../../_static/documentation_options.js"></script>
        <script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
        <script src="../../_static/jquery.js"></script>
        <script src="../../_static/underscore.js"></script>
        <script src="../../_static/doctools.js"></script>
        <script src="../../_static/translations.js"></script>
    
    <script type="text/javascript" src="../../_static/js/theme.js"></script>

    
    <script type="text/javascript" src="../../_static/js/tlcpack_theme.js"></script>
    <link rel="index" title="索引" href="../../genindex.html" />
    <link rel="search" title="搜索" href="../../search.html" />
    <link rel="next" title="Profile Models" href="../profile/index.html" />
    <link rel="prev" title="How to Use TVM Pass Instrument" href="use_pass_instrument.html" /> 
</head>

<body class="wy-body-for-nav">

   
  <div class="wy-grid-for-nav">
    
    
<header class="header">
    <div class="innercontainer">
      <div class="headerInner d-flex justify-content-between align-items-center">
          <div class="headerLogo">
               <a href="https://tvm.apache.org/"><img src=https://tvm.apache.org/assets/images/logo.svg alt="logo"></a>
          </div>

          <div id="headMenu" class="headerNav">
            <button type="button" id="closeHeadMenu" class="navCloseBtn"><img src="../../_static/img/close-icon.svg" alt="Close"></button>
             <ul class="nav">
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/community>Community</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/download>Download</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/vta>VTA</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/blog>Blog</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/docs>Docs</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvmconf.org>Conference</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://github.com/apache/tvm/>Github</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvmchinese.github.io/declaration_zh_CN.html>About-Translators</a>
                </li>
             </ul>
               <div class="responsivetlcdropdown">
                 <button type="button" class="btn-link">
                   ASF
                 </button>
                 <ul>
                     <li>
                       <a href=https://apache.org/>Apache Homepage</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/licenses/>License</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/sponsorship.html>Sponsorship</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/security/>Security</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/thanks.html>Thanks</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/events/current-event>Events</a>
                     </li>
                     <li>
                       <a href=https://www.zhihu.com/column/c_1429578595417563136>Zhihu</a>
                     </li>
                 </ul>
               </div>
          </div>
            <div class="responsiveMenuIcon">
              <button type="button" id="menuBtn" class="btn-menu"><img src="../../_static/img/menu-icon.svg" alt="Menu Icon"></button>
            </div>

            <div class="tlcDropdown">
              <div class="dropdown">
                <button type="button" class="btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                  ASF
                </button>
                <div class="dropdown-menu dropdown-menu-right">
                  <ul>
                     <li>
                       <a href=https://apache.org/>Apache Homepage</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/licenses/>License</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/sponsorship.html>Sponsorship</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/security/>Security</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/thanks.html>Thanks</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/events/current-event>Events</a>
                     </li>
                     <li>
                       <a href=https://www.zhihu.com/column/c_1429578595417563136>Zhihu</a>
                     </li>
                  </ul>
                </div>
              </div>
          </div>
       </div>
    </div>
 </header>
 
    <nav data-toggle="wy-nav-shift" class="wy-nav-side fixed">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search" >
          

          
            <a href="../../index.html">
          

          
            
            <img src="../../_static/tvm-logo-small.png" class="logo" alt="Logo"/>
          
          </a>

          
            
            
                <div class="version">
                  0.8.dev1982
                </div>
            
          

          
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>

          
        </div>

        
        <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
          
            
            
              
            
            
              <p class="caption" role="heading"><span class="caption-text">如何开始</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../install/index.html">安装 TVM</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../contribute/index.html">贡献者指南</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">用户引导</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../../tutorial/index.html">User Tutorial</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../index.html">How To Guides</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../compile_models/index.html">编译深度学习模型</a></li>
<li class="toctree-l2"><a class="reference internal" href="../deploy/index.html">TVM 部署模型和集成</a></li>
<li class="toctree-l2"><a class="reference internal" href="../work_with_relay/index.html">Work With Relay</a></li>
<li class="toctree-l2"><a class="reference internal" href="../work_with_schedules/index.html">Work With Tensor Expression and Schedules</a></li>
<li class="toctree-l2"><a class="reference internal" href="../optimize_operators/index.html">优化张量算子</a></li>
<li class="toctree-l2"><a class="reference internal" href="../tune_with_autotvm/index.html">Auto-Tune with Templates and AutoTVM</a></li>
<li class="toctree-l2"><a class="reference internal" href="../tune_with_autoscheduler/index.html">Use AutoScheduler for Template-Free Scheduling</a></li>
<li class="toctree-l2"><a class="reference internal" href="../work_with_microtvm/index.html">Work With microTVM</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="index.html">Extend TVM</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="low_level_custom_pass.html">编写自定义通行证</a></li>
<li class="toctree-l3"><a class="reference internal" href="use_pass_infra.html">How to Use TVM Pass Infra</a></li>
<li class="toctree-l3"><a class="reference internal" href="use_pass_instrument.html">How to Use TVM Pass Instrument</a></li>
<li class="toctree-l3 current"><a class="current reference internal" href="#">Bring Your Own Datatypes to TVM</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#datatype-libraries">Datatype Libraries</a></li>
<li class="toctree-l4"><a class="reference internal" href="#setup">设置</a></li>
<li class="toctree-l4"><a class="reference internal" href="#a-simple-tvm-program">A Simple TVM Program</a></li>
<li class="toctree-l4"><a class="reference internal" href="#adding-custom-datatypes">Adding Custom Datatypes</a></li>
<li class="toctree-l4"><a class="reference internal" href="#running-models-with-custom-datatypes">Running Models With Custom Datatypes</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../profile/index.html">Profile Models</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../errors.html">Handle TVM Errors</a></li>
<li class="toctree-l2"><a class="reference internal" href="../../faq.html">常见提问</a></li>
</ul>
</li>
</ul>
<p class="caption" role="heading"><span class="caption-text">开发者引导</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../dev/tutorial/index.html">Developer Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../dev/how_to/how_to.html">开发者指南</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">架构指南</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../arch/index.html">Design and Architecture</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">主题引导</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../topic/microtvm/index.html">microTVM：裸机使用TVM</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../topic/vta/index.html">VTA: Versatile Tensor Accelerator</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">参考指南</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../reference/langref/index.html">语言参考</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../reference/api/python/index.html">Python API</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../reference/api/links.html">Other APIs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../reference/publications.html">Publications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../genindex.html">索引</a></li>
</ul>

            
          
        </div>
        
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
      
      <nav class="wy-nav-top" aria-label="top navigation" data-toggle="wy-nav-top">
        
            <div class="togglemenu">

            </div>
            <div class="nav-content">
              <!-- tvm -->
              Table of content
            </div>
        
      </nav>


      <div class="wy-nav-content">
        
        <div class="rst-content">
        

          




















<div role="navigation" aria-label="breadcrumbs navigation">

  <ul class="wy-breadcrumbs">
    
      <li><a href="../../index.html">Docs</a> <span class="br-arrow">></span></li>
        
          <li><a href="../index.html">How To Guides</a> <span class="br-arrow">></span></li>
        
          <li><a href="index.html">Extend TVM</a> <span class="br-arrow">></span></li>
        
      <li>Bring Your Own Datatypes to TVM</li>
    
    
      <li class="wy-breadcrumbs-aside">
        
            
            <a href="../../_sources/how_to/extend_tvm/bring_your_own_datatypes.rst.txt" rel="nofollow"> <img src="../../_static//img/source.svg" alt="viewsource"/></a>
          
        
      </li>
    
  </ul>

  
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
            
  <div class="sphx-glr-download-link-note admonition note">
<p class="admonition-title">注解</p>
<p>点击 <a class="reference internal" href="#sphx-glr-download-how-to-extend-tvm-bring-your-own-datatypes-py"><span class="std std-ref">此处</span></a> 获取完整示例代码</p>
</div>
<div class="sphx-glr-example-title section" id="bring-your-own-datatypes-to-tvm">
<span id="sphx-glr-how-to-extend-tvm-bring-your-own-datatypes-py"></span><h1>Bring Your Own Datatypes to TVM<a class="headerlink" href="#bring-your-own-datatypes-to-tvm" title="永久链接至标题">¶</a></h1>
<p><strong>作者</strong>: <a class="reference external" href="https://github.com/gussmith23">Gus Smith</a>, <a class="reference external" href="https://github.com/hypercubestart">Andrew Liu</a></p>
<p>In this tutorial, we will show you how to utilize the Bring Your Own Datatypes framework to use your own custom datatypes in TVM.
Note that the Bring Your Own Datatypes framework currently only handles <strong>software emulated versions of datatypes</strong>.
The framework does not support compiling for custom accelerator datatypes out-of-the-box.</p>
<div class="section" id="datatype-libraries">
<h2>Datatype Libraries<a class="headerlink" href="#datatype-libraries" title="永久链接至标题">¶</a></h2>
<p>The Bring Your Own Datatypes allows users to register their own datatype implementations alongside TVM’s native datatypes (such as <code class="docutils literal notranslate"><span class="pre">float</span></code>).
In the wild, these datatype implementations often appear as libraries.
For example:</p>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/cjdelisle/libposit">libposit</a>, a posit library</p></li>
<li><p><a class="reference external" href="https://github.com/stillwater-sc/universal">Stillwater Universal</a>, a library with posits, fixed-point numbers, and other types</p></li>
<li><p><a class="reference external" href="https://github.com/ucb-bar/berkeley-softfloat-3">SoftFloat</a>, Berkeley’s software implementation of IEEE 754 floating-point</p></li>
</ul>
<p>The Bring Your Own Datatypes enables users to plug these datatype implementations into TVM!</p>
<p>In this section, we will use an example library we have already implemented, located at <code class="docutils literal notranslate"><span class="pre">3rdparty/byodt/myfloat.cc</span></code>.
This datatype, which we dubbed “myfloat”, is really just a IEE-754 float under-the-hood, but it serves a useful example
to show that any datatype can be used in the BYODT framework.</p>
</div>
<div class="section" id="setup">
<h2>设置<a class="headerlink" href="#setup" title="永久链接至标题">¶</a></h2>
<p>Since we do not use any 3rdparty library, there is no setup needed.</p>
<p>If you would like to try this with your own datatype library, first bring the library’s functions into the process space with <code class="docutils literal notranslate"><span class="pre">CDLL</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="s1">&#39;my-datatype-lib.so&#39;</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">RTLD_GLOBAL</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="a-simple-tvm-program">
<h2>A Simple TVM Program<a class="headerlink" href="#a-simple-tvm-program" title="永久链接至标题">¶</a></h2>
<p>We’ll begin by writing a simple program in TVM; afterwards, we will re-write it to use custom datatypes.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">tvm</span>
<span class="kn">from</span> <span class="nn">tvm</span> <span class="k">import</span> <span class="n">relay</span>

<span class="c1"># Our basic program: Z = X + Y</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;x&quot;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">3</span><span class="p">,),</span> <span class="n">dtype</span><span class="o">=</span><span class="s2">&quot;float32&quot;</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;y&quot;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">3</span><span class="p">,),</span> <span class="n">dtype</span><span class="o">=</span><span class="s2">&quot;float32&quot;</span><span class="p">)</span>
<span class="n">z</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="n">program</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">Function</span><span class="p">([</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">],</span> <span class="n">z</span><span class="p">)</span>
<span class="n">module</span> <span class="o">=</span> <span class="n">tvm</span><span class="o">.</span><span class="n">IRModule</span><span class="o">.</span><span class="n">from_expr</span><span class="p">(</span><span class="n">program</span><span class="p">)</span>
</pre></div>
</div>
<p>Now, we create random inputs to feed into this program using numpy:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>

<span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">seed</span><span class="p">(</span><span class="mi">23</span><span class="p">)</span>  <span class="c1"># for reproducibility</span>

<span class="n">x_input</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">rand</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="s2">&quot;float32&quot;</span><span class="p">)</span>
<span class="n">y_input</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">rand</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="s2">&quot;float32&quot;</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;x: </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">x_input</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;y: </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">y_input</span><span class="p">))</span>
</pre></div>
</div>
<p class="sphx-glr-script-out">输出:</p>
<div class="sphx-glr-script-out highlight-none notranslate"><div class="highlight"><pre><span></span>x: [0.51729786 0.9469626  0.7654598 ]
y: [0.28239584 0.22104536 0.6862221 ]
</pre></div>
</div>
<p>Finally, we’re ready to run the program:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">z_output</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">create_executor</span><span class="p">(</span><span class="n">mod</span><span class="o">=</span><span class="n">module</span><span class="p">)</span><span class="o">.</span><span class="n">evaluate</span><span class="p">()(</span><span class="n">x_input</span><span class="p">,</span> <span class="n">y_input</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;z: </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">z_output</span><span class="p">))</span>
</pre></div>
</div>
<p class="sphx-glr-script-out">输出:</p>
<div class="sphx-glr-script-out highlight-none notranslate"><div class="highlight"><pre><span></span>z: [0.7996937 1.168008  1.4516819]
</pre></div>
</div>
</div>
<div class="section" id="adding-custom-datatypes">
<h2>Adding Custom Datatypes<a class="headerlink" href="#adding-custom-datatypes" title="永久链接至标题">¶</a></h2>
<p>Now, we will do the same, but we will use a custom datatype for our intermediate computation.</p>
<p>We use the same input variables <code class="docutils literal notranslate"><span class="pre">x</span></code> and <code class="docutils literal notranslate"><span class="pre">y</span></code> as above, but before adding <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">+</span> <span class="pre">y</span></code>, we first cast both <code class="docutils literal notranslate"><span class="pre">x</span></code> and <code class="docutils literal notranslate"><span class="pre">y</span></code> to a custom datatype via the <code class="docutils literal notranslate"><span class="pre">relay.cast(...)</span></code> call.</p>
<p>Note how we specify the custom datatype: we indicate it using the special <code class="docutils literal notranslate"><span class="pre">custom[...]</span></code> syntax.
Additionally, note the “32” after the datatype: this is the bitwidth of the custom datatype. This tells TVM that each instance of <code class="docutils literal notranslate"><span class="pre">myfloat</span></code> is 32 bits wide.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
    <span class="k">with</span> <span class="n">tvm</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">PassContext</span><span class="p">(</span><span class="n">config</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;tir.disable_vectorize&quot;</span><span class="p">:</span> <span class="kc">True</span><span class="p">}):</span>
        <span class="n">x_myfloat</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">cast</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="s2">&quot;custom[myfloat]32&quot;</span><span class="p">)</span>
        <span class="n">y_myfloat</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">cast</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="s2">&quot;custom[myfloat]32&quot;</span><span class="p">)</span>
        <span class="n">z_myfloat</span> <span class="o">=</span> <span class="n">x_myfloat</span> <span class="o">+</span> <span class="n">y_myfloat</span>
        <span class="n">z</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">cast</span><span class="p">(</span><span class="n">z_myfloat</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="s2">&quot;float32&quot;</span><span class="p">)</span>
<span class="k">except</span> <span class="n">tvm</span><span class="o">.</span><span class="n">TVMError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
    <span class="c1"># Print last line of error</span>
    <span class="nb">print</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</pre></div>
</div>
<p class="sphx-glr-script-out">输出:</p>
<div class="sphx-glr-script-out highlight-none notranslate"><div class="highlight"><pre><span></span>
</pre></div>
</div>
<p>Trying to generate this program throws an error from TVM.
TVM does not know how to handle any custom datatype out of the box!
We first have to register the custom type with TVM, giving it a name and a type code:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="s2">&quot;myfloat&quot;</span><span class="p">,</span> <span class="mi">150</span><span class="p">)</span>
</pre></div>
</div>
<p>Note that the type code, 150, is currently chosen manually by the user.
See <code class="docutils literal notranslate"><span class="pre">TVMTypeCode::kCustomBegin</span></code> in <a class="reference external" href="https://github.com/apache/tvm/blob/main/include/tvm/runtime/data_type.h">include/tvm/runtime/c_runtime_api.h</a>.
Now we can generate our program again:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x_myfloat</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">cast</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="s2">&quot;custom[myfloat]32&quot;</span><span class="p">)</span>
<span class="n">y_myfloat</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">cast</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="s2">&quot;custom[myfloat]32&quot;</span><span class="p">)</span>
<span class="n">z_myfloat</span> <span class="o">=</span> <span class="n">x_myfloat</span> <span class="o">+</span> <span class="n">y_myfloat</span>
<span class="n">z</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">cast</span><span class="p">(</span><span class="n">z_myfloat</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="s2">&quot;float32&quot;</span><span class="p">)</span>
<span class="n">program</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">Function</span><span class="p">([</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">],</span> <span class="n">z</span><span class="p">)</span>
<span class="n">module</span> <span class="o">=</span> <span class="n">tvm</span><span class="o">.</span><span class="n">IRModule</span><span class="o">.</span><span class="n">from_expr</span><span class="p">(</span><span class="n">program</span><span class="p">)</span>
<span class="n">module</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">InferType</span><span class="p">()(</span><span class="n">module</span><span class="p">)</span>
</pre></div>
</div>
<p>Now we have a Relay program that uses myfloat!</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="n">program</span><span class="p">)</span>
</pre></div>
</div>
<p class="sphx-glr-script-out">输出:</p>
<div class="sphx-glr-script-out highlight-none notranslate"><div class="highlight"><pre><span></span>fn (%x: Tensor[(3), float32], %y: Tensor[(3), float32]) {
  %0 = cast(%x, dtype=&quot;custom[myfloat]32&quot;);
  %1 = cast(%y, dtype=&quot;custom[myfloat]32&quot;);
  %2 = add(%0, %1);
  cast(%2, dtype=&quot;float32&quot;)
}
</pre></div>
</div>
<p>Now that we can express our program without errors, let’s try running it!</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
    <span class="k">with</span> <span class="n">tvm</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">PassContext</span><span class="p">(</span><span class="n">config</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;tir.disable_vectorize&quot;</span><span class="p">:</span> <span class="kc">True</span><span class="p">}):</span>
        <span class="n">z_output_myfloat</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">create_executor</span><span class="p">(</span><span class="s2">&quot;graph&quot;</span><span class="p">,</span> <span class="n">mod</span><span class="o">=</span><span class="n">module</span><span class="p">)</span><span class="o">.</span><span class="n">evaluate</span><span class="p">()(</span><span class="n">x_input</span><span class="p">,</span> <span class="n">y_input</span><span class="p">)</span>
        <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;z: </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">y_myfloat</span><span class="p">))</span>
<span class="k">except</span> <span class="n">tvm</span><span class="o">.</span><span class="n">TVMError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
    <span class="c1"># Print last line of error</span>
    <span class="nb">print</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</pre></div>
</div>
<p class="sphx-glr-script-out">输出:</p>
<div class="sphx-glr-script-out highlight-none notranslate"><div class="highlight"><pre><span></span>Check failed: (lower) is false: Cast lowering function for target llvm destination type 150 source type 2 not found
</pre></div>
</div>
<p>Now, trying to compile this program throws an error.
Let’s dissect this error.</p>
<p>The error is occurring during the process of lowering the custom datatype code to code that TVM can compile and run.
TVM is telling us that it cannot find a <em>lowering function</em> for the <code class="docutils literal notranslate"><span class="pre">Cast</span></code> operation, when casting from source type 2 (<code class="docutils literal notranslate"><span class="pre">float</span></code>, in TVM), to destination type 150 (our custom datatype).
When lowering custom datatypes, if TVM encounters an operation over a custom datatype, it looks for a user-registered <em>lowering function</em>, which tells it how to lower the operation to an operation over datatypes it understands.
We have not told TVM how to lower <code class="docutils literal notranslate"><span class="pre">Cast</span></code> operations for our custom datatypes; thus, the source of this error.</p>
<p>To fix this error, we simply need to specify a lowering function:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register_op</span><span class="p">(</span>
    <span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">create_lower_func</span><span class="p">(</span>
        <span class="p">{</span>
            <span class="p">(</span><span class="mi">32</span><span class="p">,</span> <span class="mi">32</span><span class="p">):</span> <span class="s2">&quot;FloatToCustom32&quot;</span><span class="p">,</span>  <span class="c1"># cast from float32 to myfloat32</span>
        <span class="p">}</span>
    <span class="p">),</span>
    <span class="s2">&quot;Cast&quot;</span><span class="p">,</span>
    <span class="s2">&quot;llvm&quot;</span><span class="p">,</span>
    <span class="s2">&quot;float&quot;</span><span class="p">,</span>
    <span class="s2">&quot;myfloat&quot;</span><span class="p">,</span>
<span class="p">)</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">register_op(...)</span></code> call takes a lowering function, and a number of parameters which specify exactly the operation which should be lowered with the provided lowering function.
In this case, the arguments we pass specify that this lowering function is for lowering a <code class="docutils literal notranslate"><span class="pre">Cast</span></code> from <code class="docutils literal notranslate"><span class="pre">float</span></code> to <code class="docutils literal notranslate"><span class="pre">myfloat</span></code> for target <code class="docutils literal notranslate"><span class="pre">&quot;llvm&quot;</span></code>.</p>
<p>The lowering function passed into this call is very general: it should take an operation of the specified type (in this case, <cite>Cast</cite>) and return another operation which only uses datatypes which TVM understands.</p>
<p>In the general case, we expect users to implement operations over their custom datatypes using calls to an external library.
In our example, our <code class="docutils literal notranslate"><span class="pre">myfloat</span></code> library implements a <code class="docutils literal notranslate"><span class="pre">Cast</span></code> from <code class="docutils literal notranslate"><span class="pre">float</span></code> to 32-bit <code class="docutils literal notranslate"><span class="pre">myfloat</span></code> in the function <code class="docutils literal notranslate"><span class="pre">FloatToCustom32</span></code>.
To provide for the general case, we have made a helper function, <code class="docutils literal notranslate"><span class="pre">create_lower_func(...)</span></code>,
which does just this: given a dictionary, it replaces the given operation with a <code class="docutils literal notranslate"><span class="pre">Call</span></code> to the appropriate function name provided based on the op and the bit widths.
It additionally removes usages of the custom datatype by storing the custom datatype in an opaque <code class="docutils literal notranslate"><span class="pre">uint</span></code> of the appropriate width; in our case, a <code class="docutils literal notranslate"><span class="pre">uint32_t</span></code>.
For more information, see <a class="reference external" href="https://github.com/apache/tvm/blob/main/python/tvm/target/datatype.py">the source code</a>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># We can now re-try running the program:</span>
<span class="k">try</span><span class="p">:</span>
    <span class="k">with</span> <span class="n">tvm</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">PassContext</span><span class="p">(</span><span class="n">config</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;tir.disable_vectorize&quot;</span><span class="p">:</span> <span class="kc">True</span><span class="p">}):</span>
        <span class="n">z_output_myfloat</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">create_executor</span><span class="p">(</span><span class="s2">&quot;graph&quot;</span><span class="p">,</span> <span class="n">mod</span><span class="o">=</span><span class="n">module</span><span class="p">)</span><span class="o">.</span><span class="n">evaluate</span><span class="p">()(</span><span class="n">x_input</span><span class="p">,</span> <span class="n">y_input</span><span class="p">)</span>
        <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;z: </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">z_output_myfloat</span><span class="p">))</span>
<span class="k">except</span> <span class="n">tvm</span><span class="o">.</span><span class="n">TVMError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
    <span class="c1"># Print last line of error</span>
    <span class="nb">print</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</pre></div>
</div>
<p class="sphx-glr-script-out">输出:</p>
<div class="sphx-glr-script-out highlight-none notranslate"><div class="highlight"><pre><span></span>Check failed: (lower) is false: Add lowering function for target llvm type 150 not found
</pre></div>
</div>
<p>This new error tells us that the <code class="docutils literal notranslate"><span class="pre">Add</span></code> lowering function is not found, which is good news, as it’s no longer complaining about the <code class="docutils literal notranslate"><span class="pre">Cast</span></code>!
We know what to do from here: we just need to register the lowering functions for the other operations in our program.</p>
<p>Note that for <code class="docutils literal notranslate"><span class="pre">Add</span></code>, <code class="docutils literal notranslate"><span class="pre">create_lower_func</span></code> takes in a dict where the key is an integer.
For <code class="docutils literal notranslate"><span class="pre">Cast</span></code> operations, we require a 2-tuple to specify the <code class="docutils literal notranslate"><span class="pre">src_bit_length</span></code> and the <code class="docutils literal notranslate"><span class="pre">dest_bit_length</span></code>,
while for all other operations, the bit length is the same between the operands so we only require one integer to specify <code class="docutils literal notranslate"><span class="pre">bit_length</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register_op</span><span class="p">(</span>
    <span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">create_lower_func</span><span class="p">({</span><span class="mi">32</span><span class="p">:</span> <span class="s2">&quot;Custom32Add&quot;</span><span class="p">}),</span>
    <span class="s2">&quot;Add&quot;</span><span class="p">,</span>
    <span class="s2">&quot;llvm&quot;</span><span class="p">,</span>
    <span class="s2">&quot;myfloat&quot;</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register_op</span><span class="p">(</span>
    <span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">create_lower_func</span><span class="p">({(</span><span class="mi">32</span><span class="p">,</span> <span class="mi">32</span><span class="p">):</span> <span class="s2">&quot;Custom32ToFloat&quot;</span><span class="p">}),</span>
    <span class="s2">&quot;Cast&quot;</span><span class="p">,</span>
    <span class="s2">&quot;llvm&quot;</span><span class="p">,</span>
    <span class="s2">&quot;myfloat&quot;</span><span class="p">,</span>
    <span class="s2">&quot;float&quot;</span><span class="p">,</span>
<span class="p">)</span>

<span class="c1"># Now, we can run our program without errors.</span>
<span class="k">with</span> <span class="n">tvm</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">PassContext</span><span class="p">(</span><span class="n">config</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;tir.disable_vectorize&quot;</span><span class="p">:</span> <span class="kc">True</span><span class="p">}):</span>
    <span class="n">z_output_myfloat</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">create_executor</span><span class="p">(</span><span class="n">mod</span><span class="o">=</span><span class="n">module</span><span class="p">)</span><span class="o">.</span><span class="n">evaluate</span><span class="p">()(</span><span class="n">x_input</span><span class="p">,</span> <span class="n">y_input</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;z: </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">z_output_myfloat</span><span class="p">))</span>

<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;x:</span><span class="se">\t\t</span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">x_input</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;y:</span><span class="se">\t\t</span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">y_input</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;z (float32):</span><span class="se">\t</span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">z_output</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;z (myfloat32):</span><span class="se">\t</span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">z_output_myfloat</span><span class="p">))</span>

<span class="c1"># Perhaps as expected, the ``myfloat32`` results and ``float32`` are exactly the same!</span>
</pre></div>
</div>
<p class="sphx-glr-script-out">输出:</p>
<div class="sphx-glr-script-out highlight-none notranslate"><div class="highlight"><pre><span></span>z: [0.7996937 1.168008  1.4516819]
x:              [0.51729786 0.9469626  0.7654598 ]
y:              [0.28239584 0.22104536 0.6862221 ]
z (float32):    [0.7996937 1.168008  1.4516819]
z (myfloat32):  [0.7996937 1.168008  1.4516819]
</pre></div>
</div>
</div>
<div class="section" id="running-models-with-custom-datatypes">
<h2>Running Models With Custom Datatypes<a class="headerlink" href="#running-models-with-custom-datatypes" title="永久链接至标题">¶</a></h2>
<p>We will first choose the model which we would like to run with myfloat.
In this case we use <a class="reference external" href="https://arxiv.org/abs/1704.04861">Mobilenet</a>.
We choose Mobilenet due to its small size.
In this alpha state of the Bring Your Own Datatypes framework, we have not implemented any software optimizations for running software emulations of custom datatypes; the result is poor performance due to many calls into our datatype emulation library.</p>
<p>First let us define two helper functions to get the mobilenet model and a cat image.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">get_mobilenet</span><span class="p">():</span>
    <span class="n">dshape</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">224</span><span class="p">,</span> <span class="mi">224</span><span class="p">)</span>
    <span class="kn">from</span> <span class="nn">mxnet.gluon.model_zoo.vision</span> <span class="k">import</span> <span class="n">get_model</span>

    <span class="n">block</span> <span class="o">=</span> <span class="n">get_model</span><span class="p">(</span><span class="s2">&quot;mobilenet0.25&quot;</span><span class="p">,</span> <span class="n">pretrained</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
    <span class="n">shape_dict</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;data&quot;</span><span class="p">:</span> <span class="n">dshape</span><span class="p">}</span>
    <span class="k">return</span> <span class="n">relay</span><span class="o">.</span><span class="n">frontend</span><span class="o">.</span><span class="n">from_mxnet</span><span class="p">(</span><span class="n">block</span><span class="p">,</span> <span class="n">shape_dict</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">get_cat_image</span><span class="p">():</span>
    <span class="kn">from</span> <span class="nn">tvm.contrib.download</span> <span class="k">import</span> <span class="n">download_testdata</span>
    <span class="kn">from</span> <span class="nn">PIL</span> <span class="k">import</span> <span class="n">Image</span>

    <span class="n">url</span> <span class="o">=</span> <span class="s2">&quot;https://gist.githubusercontent.com/zhreshold/bcda4716699ac97ea44f791c24310193/raw/fa7ef0e9c9a5daea686d6473a62aacd1a5885849/cat.png&quot;</span>
    <span class="n">dst</span> <span class="o">=</span> <span class="s2">&quot;cat.png&quot;</span>
    <span class="n">real_dst</span> <span class="o">=</span> <span class="n">download_testdata</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">dst</span><span class="p">,</span> <span class="n">module</span><span class="o">=</span><span class="s2">&quot;data&quot;</span><span class="p">)</span>
    <span class="n">img</span> <span class="o">=</span> <span class="n">Image</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">real_dst</span><span class="p">)</span><span class="o">.</span><span class="n">resize</span><span class="p">((</span><span class="mi">224</span><span class="p">,</span> <span class="mi">224</span><span class="p">))</span>
    <span class="c1"># CoreML&#39;s standard model image format is BGR</span>
    <span class="n">img_bgr</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">img</span><span class="p">)[:,</span> <span class="p">:,</span> <span class="p">::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
    <span class="n">img</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">transpose</span><span class="p">(</span><span class="n">img_bgr</span><span class="p">,</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">))[</span><span class="n">np</span><span class="o">.</span><span class="n">newaxis</span><span class="p">,</span> <span class="p">:]</span>
    <span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">asarray</span><span class="p">(</span><span class="n">img</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="s2">&quot;float32&quot;</span><span class="p">)</span>


<span class="n">module</span><span class="p">,</span> <span class="n">params</span> <span class="o">=</span> <span class="n">get_mobilenet</span><span class="p">()</span>
</pre></div>
</div>
<p>It’s easy to execute MobileNet with native TVM:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ex</span> <span class="o">=</span> <span class="n">tvm</span><span class="o">.</span><span class="n">relay</span><span class="o">.</span><span class="n">create_executor</span><span class="p">(</span><span class="s2">&quot;graph&quot;</span><span class="p">,</span> <span class="n">mod</span><span class="o">=</span><span class="n">module</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="n">params</span><span class="p">)</span>
<span class="nb">input</span> <span class="o">=</span> <span class="n">get_cat_image</span><span class="p">()</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">ex</span><span class="o">.</span><span class="n">evaluate</span><span class="p">()(</span><span class="nb">input</span><span class="p">)</span><span class="o">.</span><span class="n">numpy</span><span class="p">()</span>
<span class="c1"># print first 10 elements</span>
<span class="nb">print</span><span class="p">(</span><span class="n">result</span><span class="o">.</span><span class="n">flatten</span><span class="p">()[:</span><span class="mi">10</span><span class="p">])</span>
</pre></div>
</div>
<p class="sphx-glr-script-out">输出:</p>
<div class="sphx-glr-script-out highlight-none notranslate"><div class="highlight"><pre><span></span>[ -7.5350165   2.0368009 -12.706646   -5.63786   -12.684058    4.0723605
   2.618876    3.4049501  -9.867913  -24.53311  ]
</pre></div>
</div>
<p>Now, we would like to change the model to use myfloat internally. To do so, we need to convert the network. To do this, we first define a function which will help us convert tensors:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">convert_ndarray</span><span class="p">(</span><span class="n">dst_dtype</span><span class="p">,</span> <span class="n">array</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Converts an NDArray into the specified datatype&quot;&quot;&quot;</span>
    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;x&quot;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="n">array</span><span class="o">.</span><span class="n">shape</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="n">array</span><span class="o">.</span><span class="n">dtype</span><span class="p">))</span>
    <span class="n">cast</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">Function</span><span class="p">([</span><span class="n">x</span><span class="p">],</span> <span class="n">x</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="n">dst_dtype</span><span class="p">))</span>
    <span class="k">with</span> <span class="n">tvm</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">PassContext</span><span class="p">(</span><span class="n">config</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;tir.disable_vectorize&quot;</span><span class="p">:</span> <span class="kc">True</span><span class="p">}):</span>
        <span class="k">return</span> <span class="n">relay</span><span class="o">.</span><span class="n">create_executor</span><span class="p">(</span><span class="s2">&quot;graph&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">evaluate</span><span class="p">(</span><span class="n">cast</span><span class="p">)(</span><span class="n">array</span><span class="p">)</span>
</pre></div>
</div>
<p>Now, to actually convert the entire network, we have written <a class="reference external" href="https://github.com/gussmith23/tvm/blob/ea174c01c54a2529e19ca71e125f5884e728da6e/python/tvm/relay/frontend/change_datatype.py#L21">a pass in Relay</a> which simply converts all nodes within the model to use the new datatype.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">tvm.relay.frontend.change_datatype</span> <span class="k">import</span> <span class="n">ChangeDatatype</span>

<span class="n">src_dtype</span> <span class="o">=</span> <span class="s2">&quot;float32&quot;</span>
<span class="n">dst_dtype</span> <span class="o">=</span> <span class="s2">&quot;custom[myfloat]32&quot;</span>

<span class="n">module</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">InferType</span><span class="p">()(</span><span class="n">module</span><span class="p">)</span>

<span class="c1"># Currently, custom datatypes only work if you run simplify_inference beforehand</span>
<span class="n">module</span> <span class="o">=</span> <span class="n">tvm</span><span class="o">.</span><span class="n">relay</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">SimplifyInference</span><span class="p">()(</span><span class="n">module</span><span class="p">)</span>

<span class="c1"># Run type inference before changing datatype</span>
<span class="n">module</span> <span class="o">=</span> <span class="n">tvm</span><span class="o">.</span><span class="n">relay</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">InferType</span><span class="p">()(</span><span class="n">module</span><span class="p">)</span>

<span class="c1"># Change datatype from float to myfloat and re-infer types</span>
<span class="n">cdtype</span> <span class="o">=</span> <span class="n">ChangeDatatype</span><span class="p">(</span><span class="n">src_dtype</span><span class="p">,</span> <span class="n">dst_dtype</span><span class="p">)</span>
<span class="n">expr</span> <span class="o">=</span> <span class="n">cdtype</span><span class="o">.</span><span class="n">visit</span><span class="p">(</span><span class="n">module</span><span class="p">[</span><span class="s2">&quot;main&quot;</span><span class="p">])</span>
<span class="n">module</span> <span class="o">=</span> <span class="n">tvm</span><span class="o">.</span><span class="n">relay</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">InferType</span><span class="p">()(</span><span class="n">module</span><span class="p">)</span>

<span class="c1"># We also convert the parameters:</span>
<span class="n">params</span> <span class="o">=</span> <span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="n">convert_ndarray</span><span class="p">(</span><span class="n">dst_dtype</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">params</span><span class="o">.</span><span class="n">items</span><span class="p">()}</span>

<span class="c1"># We also need to convert our input:</span>
<span class="nb">input</span> <span class="o">=</span> <span class="n">convert_ndarray</span><span class="p">(</span><span class="n">dst_dtype</span><span class="p">,</span> <span class="nb">input</span><span class="p">)</span>

<span class="c1"># Finally, we can try to run the converted model:</span>
<span class="k">try</span><span class="p">:</span>
    <span class="c1"># Vectorization is not implemented with custom datatypes.</span>
    <span class="k">with</span> <span class="n">tvm</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">PassContext</span><span class="p">(</span><span class="n">config</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;tir.disable_vectorize&quot;</span><span class="p">:</span> <span class="kc">True</span><span class="p">}):</span>
        <span class="n">result_myfloat</span> <span class="o">=</span> <span class="n">tvm</span><span class="o">.</span><span class="n">relay</span><span class="o">.</span><span class="n">create_executor</span><span class="p">(</span><span class="s2">&quot;graph&quot;</span><span class="p">,</span> <span class="n">mod</span><span class="o">=</span><span class="n">module</span><span class="p">)</span><span class="o">.</span><span class="n">evaluate</span><span class="p">(</span><span class="n">expr</span><span class="p">)(</span>
            <span class="nb">input</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span>
        <span class="p">)</span>
<span class="k">except</span> <span class="n">tvm</span><span class="o">.</span><span class="n">TVMError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
    <span class="nb">print</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</pre></div>
</div>
<p class="sphx-glr-script-out">输出:</p>
<div class="sphx-glr-script-out highlight-none notranslate"><div class="highlight"><pre><span></span>Check failed: (lower) is false: FloatImm lowering function for target llvm type 150 not found
</pre></div>
</div>
<p>When we attempt to run the model, we get a familiar error telling us that more funcions need to be registerd for myfloat.</p>
<p>Because this is a neural network, many more operations are required.
Here, we register all the needed functions:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register_op</span><span class="p">(</span>
    <span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">create_lower_func</span><span class="p">({</span><span class="mi">32</span><span class="p">:</span> <span class="s2">&quot;FloatToCustom32&quot;</span><span class="p">}),</span>
    <span class="s2">&quot;FloatImm&quot;</span><span class="p">,</span>
    <span class="s2">&quot;llvm&quot;</span><span class="p">,</span>
    <span class="s2">&quot;myfloat&quot;</span><span class="p">,</span>
<span class="p">)</span>

<span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register_op</span><span class="p">(</span>
    <span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">lower_ite</span><span class="p">,</span> <span class="s2">&quot;Call&quot;</span><span class="p">,</span> <span class="s2">&quot;llvm&quot;</span><span class="p">,</span> <span class="s2">&quot;myfloat&quot;</span><span class="p">,</span> <span class="n">intrinsic_name</span><span class="o">=</span><span class="s2">&quot;tir.if_then_else&quot;</span>
<span class="p">)</span>

<span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register_op</span><span class="p">(</span>
    <span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">lower_call_pure_extern</span><span class="p">,</span>
    <span class="s2">&quot;Call&quot;</span><span class="p">,</span>
    <span class="s2">&quot;llvm&quot;</span><span class="p">,</span>
    <span class="s2">&quot;myfloat&quot;</span><span class="p">,</span>
    <span class="n">intrinsic_name</span><span class="o">=</span><span class="s2">&quot;tir.call_pure_extern&quot;</span><span class="p">,</span>
<span class="p">)</span>

<span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register_op</span><span class="p">(</span>
    <span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">create_lower_func</span><span class="p">({</span><span class="mi">32</span><span class="p">:</span> <span class="s2">&quot;Custom32Mul&quot;</span><span class="p">}),</span>
    <span class="s2">&quot;Mul&quot;</span><span class="p">,</span>
    <span class="s2">&quot;llvm&quot;</span><span class="p">,</span>
    <span class="s2">&quot;myfloat&quot;</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register_op</span><span class="p">(</span>
    <span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">create_lower_func</span><span class="p">({</span><span class="mi">32</span><span class="p">:</span> <span class="s2">&quot;Custom32Div&quot;</span><span class="p">}),</span>
    <span class="s2">&quot;Div&quot;</span><span class="p">,</span>
    <span class="s2">&quot;llvm&quot;</span><span class="p">,</span>
    <span class="s2">&quot;myfloat&quot;</span><span class="p">,</span>
<span class="p">)</span>

<span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register_op</span><span class="p">(</span>
    <span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">create_lower_func</span><span class="p">({</span><span class="mi">32</span><span class="p">:</span> <span class="s2">&quot;Custom32Sqrt&quot;</span><span class="p">}),</span>
    <span class="s2">&quot;Call&quot;</span><span class="p">,</span>
    <span class="s2">&quot;llvm&quot;</span><span class="p">,</span>
    <span class="s2">&quot;myfloat&quot;</span><span class="p">,</span>
    <span class="n">intrinsic_name</span><span class="o">=</span><span class="s2">&quot;tir.sqrt&quot;</span><span class="p">,</span>
<span class="p">)</span>

<span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register_op</span><span class="p">(</span>
    <span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">create_lower_func</span><span class="p">({</span><span class="mi">32</span><span class="p">:</span> <span class="s2">&quot;Custom32Sub&quot;</span><span class="p">}),</span>
    <span class="s2">&quot;Sub&quot;</span><span class="p">,</span>
    <span class="s2">&quot;llvm&quot;</span><span class="p">,</span>
    <span class="s2">&quot;myfloat&quot;</span><span class="p">,</span>
<span class="p">)</span>

<span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register_op</span><span class="p">(</span>
    <span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">create_lower_func</span><span class="p">({</span><span class="mi">32</span><span class="p">:</span> <span class="s2">&quot;Custom32Exp&quot;</span><span class="p">}),</span>
    <span class="s2">&quot;Call&quot;</span><span class="p">,</span>
    <span class="s2">&quot;llvm&quot;</span><span class="p">,</span>
    <span class="s2">&quot;myfloat&quot;</span><span class="p">,</span>
    <span class="n">intrinsic_name</span><span class="o">=</span><span class="s2">&quot;tir.exp&quot;</span><span class="p">,</span>
<span class="p">)</span>

<span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register_op</span><span class="p">(</span>
    <span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">create_lower_func</span><span class="p">({</span><span class="mi">32</span><span class="p">:</span> <span class="s2">&quot;Custom32Max&quot;</span><span class="p">}),</span>
    <span class="s2">&quot;Max&quot;</span><span class="p">,</span>
    <span class="s2">&quot;llvm&quot;</span><span class="p">,</span>
    <span class="s2">&quot;myfloat&quot;</span><span class="p">,</span>
<span class="p">)</span>

<span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">register_min_func</span><span class="p">(</span>
    <span class="n">tvm</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">datatype</span><span class="o">.</span><span class="n">create_min_lower_func</span><span class="p">({</span><span class="mi">32</span><span class="p">:</span> <span class="s2">&quot;MinCustom32&quot;</span><span class="p">},</span> <span class="s2">&quot;myfloat&quot;</span><span class="p">),</span>
    <span class="s2">&quot;myfloat&quot;</span><span class="p">,</span>
<span class="p">)</span>
</pre></div>
</div>
<p>Note we are making use of two new functions: <code class="docutils literal notranslate"><span class="pre">register_min_func</span></code> and <code class="docutils literal notranslate"><span class="pre">create_min_lower_func</span></code>.</p>
<p><code class="docutils literal notranslate"><span class="pre">register_min_func</span></code> takes in an integer <code class="docutils literal notranslate"><span class="pre">num_bits</span></code> for the bit length, and should return an operation
representing the minimum finite representable value for the custom data type with the specified bit length.</p>
<p>Similar to <code class="docutils literal notranslate"><span class="pre">register_op</span></code> and <code class="docutils literal notranslate"><span class="pre">create_lower_func</span></code>, the <code class="docutils literal notranslate"><span class="pre">create_min_lower_func</span></code> handles the general case
where the minimum representable custom datatype value is implemented using calls to an external library.</p>
<p>Now we can finally run the model:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Vectorization is not implemented with custom datatypes.</span>
<span class="k">with</span> <span class="n">tvm</span><span class="o">.</span><span class="n">transform</span><span class="o">.</span><span class="n">PassContext</span><span class="p">(</span><span class="n">config</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;tir.disable_vectorize&quot;</span><span class="p">:</span> <span class="kc">True</span><span class="p">}):</span>
    <span class="n">result_myfloat</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">create_executor</span><span class="p">(</span><span class="n">mod</span><span class="o">=</span><span class="n">module</span><span class="p">)</span><span class="o">.</span><span class="n">evaluate</span><span class="p">(</span><span class="n">expr</span><span class="p">)(</span><span class="nb">input</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">)</span>
    <span class="n">result_myfloat</span> <span class="o">=</span> <span class="n">convert_ndarray</span><span class="p">(</span><span class="n">src_dtype</span><span class="p">,</span> <span class="n">result_myfloat</span><span class="p">)</span><span class="o">.</span><span class="n">numpy</span><span class="p">()</span>
    <span class="c1"># print first 10 elements</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">result_myfloat</span><span class="o">.</span><span class="n">flatten</span><span class="p">()[:</span><span class="mi">10</span><span class="p">])</span>

<span class="c1"># Again, note that the output using 32-bit myfloat exactly the same as 32-bit floats,</span>
<span class="c1"># because myfloat is exactly a float!</span>
<span class="n">np</span><span class="o">.</span><span class="n">testing</span><span class="o">.</span><span class="n">assert_array_equal</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">result_myfloat</span><span class="p">)</span>
</pre></div>
</div>
<p class="sphx-glr-script-out">输出:</p>
<div class="sphx-glr-script-out highlight-none notranslate"><div class="highlight"><pre><span></span>[ -7.5350165   2.0368009 -12.706646   -5.63786   -12.684058    4.0723605
   2.618876    3.4049501  -9.867913  -24.53311  ]
</pre></div>
</div>
<div class="sphx-glr-footer class sphx-glr-footer-example docutils container" id="sphx-glr-download-how-to-extend-tvm-bring-your-own-datatypes-py">
<div class="sphx-glr-download docutils container">
<p><a class="reference download internal" download="" href="../../_downloads/ee99205e9f2e4f54c0fb7925008a5354/bring_your_own_datatypes.py"><code class="xref download docutils literal notranslate"><span class="pre">Python</span> <span class="pre">源码下载:</span> <span class="pre">bring_your_own_datatypes.py</span></code></a></p>
</div>
<div class="sphx-glr-download docutils container">
<p><a class="reference download internal" download="" href="../../_downloads/b11795df0596a55e4982bf895d0c8c38/bring_your_own_datatypes.ipynb"><code class="xref download docutils literal notranslate"><span class="pre">Jupyter</span> <span class="pre">notebook</span> <span class="pre">下载:</span> <span class="pre">bring_your_own_datatypes.ipynb</span></code></a></p>
</div>
</div>
<p class="sphx-glr-signature"><a class="reference external" href="https://sphinx-gallery.github.io">Gallery generated by Sphinx-Gallery</a></p>
</div>
</div>


           </div>
           
          </div>
          

<footer>

    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="../profile/index.html" class="btn btn-neutral float-right" title="Profile Models" accesskey="n" rel="next">下一个 <span class="fa fa-arrow-circle-right"></span></a>
      
      
        <a href="use_pass_instrument.html" class="btn btn-neutral float-left" title="How to Use TVM Pass Instrument" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left"></span> 上一个</a>
      
    </div>

<div id="button" class="backtop"><img src="../../_static//img/right.svg" alt="backtop"/> </div>
<section class="footerSec">
    <div class="footerHeader">
      <ul class="d-flex align-md-items-center justify-content-between flex-column flex-md-row">
        <li class="copywrite d-flex align-items-center">
          <h5 id="copy-right-info">© 2020 Apache Software Foundation | All right reserved</h5>
        </li>
      </ul>

    </div>

    <ul>
      <li class="footernote">Copyright © 2020 The Apache Software Foundation. Apache TVM, Apache, the Apache feather, and the Apache TVM project logo are either trademarks or registered trademarks of the Apache Software Foundation.</li>
    </ul>

</section>
</footer>
        </div>
      </div>

    </section>

  </div>
  

    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>

  </body>
  <script type="text/javascript">
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script>

  
  
    
    <!-- Theme Analytics -->
    <script>
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-75982049-2', 'auto');
    ga('send', 'pageview');
    </script>

    
   

</body>
</html>